electron中的ipc通信(三)

您所在的位置:网站首页 electron webview 通信 electron中的ipc通信(三)

electron中的ipc通信(三)

2024-02-01 17:15| 来源: 网络整理| 查看: 265

深圳的天气骤降,还是挺冷的,大家要注意保暖。微信公众号:[猫十二的日常],欢迎留言和指出问题a

上次写了关于ipc通讯的一些方式,主要都是web页面向主进程通讯,主进程回复通讯,这个感觉和http有点相似,发送一个http资源的请求,服务返回一个资源结果,现在我们主要看这两个点

主进程主动推消息给web渲染进程的 web渲染进程之间的通讯 主进程向渲染进程主动通信

这个可能就牵扯到了一个比较重要的APi,BrowserWindow 这个是用于创建和控制浏览器窗口的,只能在主进程进行调用,当然也是这个家伙创建的渲染进程

const { BrowserWindow } = require('electron') const win = new BrowserWindow({ width: 800, height: 600 }) win.loadURL('http://github.com') const contents = win.webContents console.log(contents)

这个创建之后返回的win下面的webContents就是可以渲染和控制web页面的api模块,咱们不会深入展开的,主要针对通讯讲一讲

contents.send(channel, ...args) channel String 事件名称 ...args any[] 传递的参数,和上节一样

目录准备,修改和删除都在这几个文件操作

my-electron-app/ ├── package.json ├── main.js // 这个就是主进程 ├── renderer.js // 这个就是渲染进程 └── index.html //web页面

index.html

Electron演示 Electron演示

renderer.js

const { ipcRenderer } = require("electron"); ipcRenderer.on("message", (event, arg) => { console.log("主进程老哥,主动推消息了:", arg); });

main.js

const { app, BrowserWindow, ipcMain } = require("electron"); function createWindow() { const win = new BrowserWindow({ width: 1920, height: 1080, webPreferences: { nodeIntegration: true, contextIsolation: false, }, }); const contents = win.webContents; contents.openDevTools(); //打开调试工具 win.loadFile("index.html"); contents.on("did-finish-load", () => { //页面加载完成触发的回调函数 console.log("load"); contents.send("message", "我看到你加载完了,给你发个信息"); }); } app.whenReady().then(createWindow); app.on("window-all-closed", () => { if (process.platform !== "darwin") { app.quit(); } }); app.on("activate", () => { if (BrowserWindow.getAllWindows().length === 0) { createWindow(); } });

image-20210111143013911

contents.sendToFrame(frameId, channel, ...args) 通过frameId给渲染进程中嵌入的webview发送消息 frameId Integer | [number, number] channel String ...args any[]

首先如何拿到框架的id?

第一种渲染进程主动调用方法去拿到id,然后调用取方法

console.log('My frameId is:', require('electron').webFrame.routingId) //然后你把这个传给主进程

第二种主进程通过监听的函数去拿,因为渲染进程发消息会触发主进程的事件,我们就可以通过event去拿

ipcMain.on('ping', (event) => { console.info('Message came from frameId:', event.frameId) })

index.html

DOCTYPE html> Electron演示 Electron演示 //具体查api

main.js

const { app, BrowserWindow, ipcMain } = require("electron"); let win; function createWindow() { win = new BrowserWindow({ width: 1920, height: 1080, webPreferences: { nodeIntegration: true, webviewTag: true, //需要设置webview来启用这个 }, }); const contents = win.webContents; contents.openDevTools(); //打开调试工具 win.loadFile("index.html"); contents.on("did-finish-load", () => { //页面加载完成触发的回调函数 console.log("load"); // contents.send("message", "我看到你加载完了,给你发个信息"); }); } ipcMain.on("getFrameId", (event, arg) => { console.log("收到了FrameId", arg); //收到了FrameId 1 console.log("event收到了FrameId", event.frameId); //event收到了FrameId 1 win.webContents.sendToFrame( event.frameId, "message", "我看到你加载完了,给你发个信息" ); }); app.whenReady().then(createWindow); app.on("window-all-closed", () => { if (process.platform !== "darwin") { app.quit(); } }); app.on("activate", () => { if (BrowserWindow.getAllWindows().length === 0) { createWindow(); } });

other.html

其他页面 const { ipcRenderer, webFrame } = require("electron"); ipcRenderer.send("getFrameId", webFrame.routingId); ipcRenderer.on("message", (event, arg) => { console.log("(renderer2)主进程老哥,主动推消息了:", arg); });

renderer.js

const { ipcRenderer, webFrame } = require("electron"); console.log("My frameId is:", webFrame.routingId); ipcRenderer.on("message", (event, arg) => { console.log("(renderer2)主进程老哥,主动推消息了:", arg); });

结果

image-20210111151212189

image-20210111151228633

contents.postMessage(channel, message, [transfer]) 利用原生的webworker进行通讯 channel String message any transfer MessagePortMain[] (optional)

只写关键性代码,具体的代码参看最上面的改动,对照一下

main.js

contents.on("did-finish-load", () => { const { port1, port2 } = new MessageChannelMain(); contents.postMessage("message", "我看到你加载完了,给你发个信息", [port1]); port2.postMessage("再给你发个消息"); });

renderer.js

ipcRenderer.on("message", (event, arg) => { const [port] = event.ports; console.log(arg, event); port.onmessage = (arg) => { console.log(arg.data); }; });

结果

我看到你加载完了,给你发个信息 Object

再给你发个消息

以上就是借助 webContent功能模块 主进程向渲染进程通信

渲染进程互相通信 ipcRenderer.sendTo(webContentsId, channel, ...args) webContentsId Number 渲染进程的id channel String ...args any[]

获取渲染进程的id

可以在创建窗口的时候保存每个窗口的id 或者创建一个主进程事件获取每个渲染进程的id

main.js

const { app, BrowserWindow, ipcMain } = require("electron"); let win; let ids = { "index.html": null, }; function createWindow() { win = new BrowserWindow({ width: 1920, height: 1080, webPreferences: { nodeIntegration: true, contextIsolation: false, webviewTag: true, //需要设置webview来启用这个 }, }); const contents = win.webContents; contents.openDevTools(); //打开调试工具 win.loadFile("index.html"); ids["index.html"] = contents.id; } ipcMain.on("registerFrameId", (event, arg) => { console.log(arg); ids = Object.assign(ids, arg); }); ipcMain.on("getFrameId", (event, arg) => { event.returnValue = ids[arg]; }); app.whenReady().then(createWindow); app.on("window-all-closed", () => { if (process.platform !== "darwin") { app.quit(); } }); app.on("activate", () => { if (BrowserWindow.getAllWindows().length === 0) { createWindow(); } });

renderer.js

const { ipcRenderer } = require("electron"); onload = () => { const webview = document.querySelector("webview"); webview.addEventListener("did-finish-load", () => { webview.openDevTools(); let otherId = ipcRenderer.sendSync("getFrameId", "other.html"); console.log(otherId); ipcRenderer.sendTo(otherId, "webview", "other老弟,喝一口"); }); ipcRenderer.on("webview", (event, arg) => { console.log("来自other.html消息:", arg); }); };

other.html

其他页面 onload = () => { const { ipcRenderer, remote //从remote模块获取到窗体的唯一id } = require("electron"); // let webContent = webContents.getFocusedWebContents() const webContent = remote.getCurrentWebContents(); console.log(webContent.id) ipcRenderer.send("registerFrameId", { 'other.html': webContent.id }); let indexId = ipcRenderer.sendSync('getFrameId', 'index.html') ipcRenderer.sendTo(indexId, "webview", "index老哥,给你发消息了"); ipcRenderer.on("webview", (event, arg) => { document.write("来自html.html消息:", arg) }); }

Index.html

Electron演示 Electron演示

结果

image-20210111165640002

ipcRenderer.sendToHost(channel, ...args) channel String ...args any[]

就像 ipcRenderer.send,不同的是消息会被发送到 host 页面上的 元素,而不是主进程

需要用到webview的一个事件监听 'ipc-message' 监听发布的消息

具体改动这个地方

other.html

其他页面 asdada const { ipcRenderer, } = require("electron"); ipcRenderer.on('ping', (event, arg) => { console.log("来自主页面的回话", arg) ipcRenderer.sendToHost('message', '小哥我给你发信息了') })

renderer.js

onload = () => { const webview = document.querySelector("webview"); webview.addEventListener("ipc-message", (event) => { console.log("来自webview的回话:", event); }); webview.addEventListener("did-finish-load", () => { webview.openDevTools(); webview.send("ping", "理我一下"); }); };

结果

image-20210111182953481

到这基本把ipc的基本的通信方法讲完了,剩下的就是各种炫技的方式了。看了下其他人的写法还是自己的路还是蛮长的,加油

如果觉得我的文章还可以,点个赞或者关注一下下,还有精彩的故事等着你哦,还可以云撸猫



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3